package com.android.dialer.extendboard;

import android.util.Log;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;

public class DataParseHelper {

    // Magic 数字
    private static final String TAG = "DataParseHelper";
    private static final short MAGIC_NUMBER = (short) 0xABAB;

    // 状态机状态
    private enum State {
        WAIT_MAGIC, WAIT_TYPE, WAIT_LENGTH, WAIT_DATA
    }

    private State currentState = State.WAIT_MAGIC;
    private ByteBuffer buffer = ByteBuffer.allocate(1024).order(ByteOrder.LITTLE_ENDIAN);
    private int expectedLength = 0;
    private long lastReceiveTime = 0;
    private USBMessage currentMessage = null;

    // 回调接口定义
    public interface OnDataParsedListener {
        void onMessageParsed(USBMessage message);
    }

    private OnDataParsedListener listener;

    /**
     * 设置回调监听器
     *
     * @param listener 回调接口实现
     */
    public void setDataParseListener(OnDataParsedListener listener) {
        this.listener = listener;
    }

    /**
     * 解析流数据
     *
     * @param data 接收到的字节数组
     * @param length 接收到的字节数组长度
     */
    public void parseStream(byte[] data, int length) {
        long currentTime = System.currentTimeMillis();

        // 超时处理
        if (currentTime - lastReceiveTime > 5000) {
            resetState();
        }
        lastReceiveTime = currentTime;

        // dump data into hex string
        StringBuilder hexString = new StringBuilder();
        for (int i = 0; i < length; i++) {
            hexString.append(String.format("%02X ", data[i]));
        }
        Log.d(TAG, "parseStream: data: " + hexString.toString());


        byte b;
        for (int i = 0; i < length; i++) {
            b = data[i];
            switch (currentState) {
                case WAIT_MAGIC:
                    //Log.d(TAG, "parseStream: WAIT_MAGIC");
                    buffer.put(b);
                    if (buffer.position() == 2) {
                        buffer.flip();
                        if (buffer.getShort() == MAGIC_NUMBER) {
                            currentState = State.WAIT_TYPE;
                        }
                        buffer.clear();
                    }
                    break;

                case WAIT_TYPE:
                    //Log.d(TAG, "parseStream: WAIT_TYPE b=" + String.format("%02X", b));
                    buffer.put(b);
                    if (buffer.position() == 1) {
                        int msgType;
                        buffer.flip();
                        msgType = (buffer.get() & 0xff);
                        buffer.clear();
                        currentMessage = new USBMessage(msgType);
                        //Log.d(TAG, "parseStream: WAIT_TYPE messageType: " + currentMessage.getMessageType());
                        currentState = State.WAIT_LENGTH;
                    }
                    break;

                case WAIT_LENGTH:
                    //Log.d(TAG, "parseStream: WAIT_LENGTH");
                    buffer.put(b);
                    if (buffer.position() == 2) {
                        buffer.flip();
                        expectedLength = buffer.getShort();
                        buffer.clear();
                        //Log.d(TAG, "parseStream: WAIT_LENGTH expectedLength: " + expectedLength);
                        if (expectedLength > 0 && expectedLength < 512) {
                            currentState = State.WAIT_DATA;
                        } else {
                            resetState();
                        }
                    }
                    break;

                case WAIT_DATA:
                    //Log.d(TAG, "parseStream: WAIT_DATA expectedLength: " + expectedLength);
                    buffer.put(b);
                    //Log.d(TAG, "parseStream: WAIT_DATA buffer.position(): " + buffer.position());
                    if (buffer.position() == expectedLength) {
                        byte[] messageData = new byte[expectedLength];
                        buffer.flip();
                        buffer.get(messageData);

                        if (currentMessage != null) {
                            currentMessage.setData(messageData);
                            handleMessage(currentMessage);
                            currentMessage = null;
                        }
                        resetState();
                    }
                    break;
            }
        }
    }


    /**
     * 处理解析后的消息
     *
     * @param data 消息数据
     */
    private void handleMessage(USBMessage message) {
        if (listener != null) {
            listener.onMessageParsed(message);
        }
    }

    /**
     * 重置状态机
     */
    private void resetState() {
        currentMessage = null;
        currentState = State.WAIT_MAGIC;
        buffer.clear();
        expectedLength = 0;
    }
}
